package com.lyz.redis.service;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HashRedisService<V> extends RedisService<String,V>{
    public HashRedisService(RedisTemplate<String, V> redisTemplate) {
        super(redisTemplate);
    }

    /**
     * hash key 不存在时新增，已存在时修改哈希表字段的值。
     * @param k redis key
     * @param hk hash key
     * @param v hash value
     */
    public void set(String k,String hk,V v){
        this.redisTemplate.opsForHash().put(k,hk,v);
    }

    /**
     * 只有在字段 hash key 不存在时，设置哈希表字段的值。
     * @param k redis key
     * @param hk hash key
     * @param v hash value
     */
    public Boolean setIfAbsent(String k,String hk,V v){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.putIfAbsent(k, hk, v);
    }

    public V get(String k,String hashKey){
        HashOperations<String, String, V> hashOps = this.redisTemplate.opsForHash();
        return hashOps.get(k,hashKey);
    }

    /**
     * 删除Hash表中的值
     * @param k redisKey
     * @param hk HashKey
     */
    public Long del(String k,String... hk){
        return this.redisTemplate.opsForHash().delete(k,(Object) hk);
    }

    /**
     * HashKey是否存在
     * @param k redisKey
     * @param hk HashKey
     * @return 是否存在
     */
    public Boolean exists(String k,String hk){
        return this.redisTemplate.opsForHash().hasKey(k,hk);
    }

    /**
     * 获取所有HashValue
     * @param k redisKey
     * @return HVs
     */
    public List<V> getAllValues(String k){
        HashOperations<String, Object, V> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.values(k);
    }

    /**
     * 获取在哈希表中指定 key 的所有字段和值
     * @param k redisKey
     * @return Map<String,V>
     */
    public Map<String, V> getAllHash(String k){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
         return hashOperations.entries(k);
    }

    /**
     * 为哈希表 key 中的指定字段的整数值加上增量 increment 。
     * @param k redis key
     * @param hk Hash key
     * @param delta 增量值
     * @return 结果值
     */
    public Long increment(String k,String hk,Long delta){
        HashOperations<String, String, Long> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.increment(k,hk,delta);
    }

    /**
     * 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
     * @param k redis key
     * @param hk Hash key
     * @param delta 增量值
     * @return 结果值
     */
    public Double increment(String k,String hk,Double delta){
        HashOperations<String, String, Double> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.increment(k,hk,delta);
    }

    /**
     * 获取哈希表中的所有字段
     * @param k redisKey
     * @return Set
     */
    public Set<String> getAllHashKey(String k){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.keys(k);
    }

    /**
     * Key对应的值数量
     * @param k redisKey
     * @return 值的数量
     */
    public Long size(String k){
        return this.redisTemplate.opsForHash().size(k);
    }

    /**
     * 获取所有给定字段的值
     * @param k redis key
     * @param hks Hash keys
     * @return Hash value list
     */
    public List<V> multiGet(String k, Collection<String> hks){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
        return hashOperations.multiGet(k,hks);
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中。
     * @param k
     * @param kvs
     * @return
     */
    public Long multiSet(String k,Map<String,V> kvs){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
        hashOperations.putAll(k,kvs);
        return hashOperations.size(k);
    }

    /**
     * 迭代哈希表中的键值对。
     * @param k redis key
     * @param kvHandler 迭代值处理
     * @param pattern hash key 正则表达式
     */
    public void scan(String k, ScanHandler<V> kvHandler, String pattern){
        HashOperations<String, String, V> hashOperations = this.redisTemplate.opsForHash();
        Cursor<Map.Entry<String, V>> cursor = hashOperations.scan(k, ScanOptions.scanOptions().match(pattern).count(1000).build());
        while (cursor.hasNext()){
            Map.Entry<String,V> entry = cursor.next();
            String key = entry.getKey();
            V value = entry.getValue();
            kvHandler.handle(key,value);
        }
        cursor.close();
    }

    public interface ScanHandler<V> {

        /**
         * 处理key value
         * @param k hash key
         * @param v hash value
         */
        void handle(String k, V v);
    }
}
